
/*
  DustSensor
  Measures the Sensordata from a STBM 271 Dust Sensor Module
  Hannes Hassler 2012
  GNU GENERAL PUBLIC LICENSE (GPL3)
  http://www.gnu.org/licenses/gpl-3.0.html 
 */
 
#define PIN_V_OUT1  3
#define PIN_V_OUT2  2

#define COUNTER_LIMIT 120

#define SEGLengthArrLength 20

char ch;

long numberOfSamples=500000;
int measurementRounds=1;

long counter=COUNTER_LIMIT;

float sumAverage=1;
float average=0;
int sampleN=10;

int segLengthArrLength=SEGLengthArrLength;
long segLength[SEGLengthArrLength];
int segLenIdx=0;

void setup() { 
  pinMode(PIN_V_OUT1, INPUT);     
  pinMode(PIN_V_OUT2, INPUT);
  Serial.begin(9600);
}

void loop() {
  static int v = 0; 

 if (Serial.available()) { 
      ch = Serial.read();  
      switch(ch) {
       case '0'...'9':
          v = v * 10 + ch - '0';
          break;
        case 'e':
          showln("test val:",v);                      
          v = 0; break; 
        case 'a':         
         showln("measure Rounds:",measurementRounds); 
         showln("number of Samples:",numberOfSamples);  
         break;        
        case 'm':
          showln("measure Rounds:",measurementRounds); 
        case 'M':
          measurementRounds=v;
          showln("new measure Rounds:",measurementRounds); 
          v=0;
          break;
        case 'n':
          showln("number of Samples:",numberOfSamples);                                
          break;
        case 'N':
          numberOfSamples=v;
          showln("new number of Samples:",numberOfSamples); 
          v=0;
          break;
    }
  }  
  
  
  if (counter>COUNTER_LIMIT) {     
    
     average=smartMeasure(PIN_V_OUT2, numberOfSamples);  
     sumAverage=((sumAverage*sampleN)+average)/(sampleN+1);
     showln("smartPerc=",sumAverage);
     
    /*average=mediumMeasure(PIN_V_OUT2, measurementRounds, numberOfSamples);
    if (average>0.0) {
      sumAverage=((sumAverage*sampleN)+average)/(sampleN+1);
      showln("m.a.p.",sumAverage);
    }*/
    
    counter=0;
  }  
  counter++;
             
}

void showln(char nameStr[], double val) {
  Serial.print(nameStr);    
  Serial.println(val);
  
}

void show(char nameStr[], double val) {
  Serial.print(nameStr);
  Serial.print(val);
}


void showSegLength() {
  int margIdx=50;
  int tabIdx=0;
  if (segLenIdx<1) {
    Serial.println("seqLenIdx=0");
  } else {
    for (int lsegIdx=0;lsegIdx<segLenIdx;lsegIdx++) {      
        Serial.print(";");
        if (tabIdx<margIdx) {           
          Serial.print(segLength[lsegIdx]);   
          tabIdx++;
        } else {        
          Serial.println(segLength[lsegIdx]);           
          tabIdx=0;
        }     
    }
    Serial.println(" "); 
  }
  
}

void resetSegLength() {  
  for (int lsegIdx=0;lsegIdx<segLengthArrLength;lsegIdx++) {
      segLength[lsegIdx]=0;
  }
  segLenIdx=0;  
}

float mediumMeasure(int pin, int times, long numberOfSamples) {
     float sum=0;
     int dontCount=0;
     float average=0.0;
     for (int i=0;i<times;i++) {
       resetSegLength();
       float measureVal=measure(pin, numberOfSamples);
       if (measureVal>0.0) {
         sum=sum+measureVal;
       } else {
         dontCount++;
         showSegLength();
       }
     }
     if (times-dontCount>0) {
         average=sum/(times-dontCount);
     } 
     return average;
}

float measure(int pin, long numOfSamples) {
  
  int pinVal=0;
  long highCount=0;
  long lowCount=0;
  boolean prevValWasHigh=true;
  long highSegmentLength=0;
  long lowSegmentLength=0;
  for (long i=0;i<numOfSamples;i++) {    
      pinVal = digitalRead(pin);
      if (pinVal==HIGH) {
         highCount++;
         
         if (prevValWasHigh) {
            highSegmentLength++;
         } else {
            highSegmentLength=1;       
            if (segLenIdx<segLengthArrLength-1) { 
              segLength[segLenIdx]=0;
              segLength[segLenIdx+1]=lowSegmentLength;
              lowSegmentLength=0;
              segLenIdx=segLenIdx+2;
            }
         }
         
         prevValWasHigh=true;
      } else {
        lowCount++;
        
        if (prevValWasHigh) {
            lowSegmentLength=1;       
            if (segLenIdx<segLengthArrLength-1) { 
              segLength[segLenIdx]=1;
              segLength[segLenIdx+1]=highSegmentLength;
              highSegmentLength=0;
              segLenIdx=segLenIdx+2;
            }          
            
         } else {
            lowSegmentLength++;
         }
        
        
        prevValWasHigh=false;
      }        
  }  
  long sum=highCount+lowCount;
  long percentageby100=(lowCount*10000)/sum;
  float percentageby100f=percentageby100;
  float percentage=percentageby100f/100.0;
  return percentage;
}


float smartMeasure(int pin, long numOfSamples) {
  
  int prevPinVal=HIGH;
  int pinVal=HIGH;
  long highCount=0;
  long lowCount=0;
  
  long highSegmentLength=0;
  long lowSegmentLength=0;  
  
  int segLengthIdx=0;
  
  for (long i=0;i<numOfSamples;i++) {   
    
      prevPinVal=pinVal;
      pinVal = digitalRead(pin);      
      
      if (prevPinVal==HIGH && pinVal==LOW) {   
       highCount=highCount+highSegmentLength;
       lowCount=lowCount+lowSegmentLength; 
       lowSegmentLength=1;
       highSegmentLength=0;         
      }
      
      if (segLengthIdx>=segLengthArrLength-1) {          
          segLengthIdx=0;
      }
      
      if (prevPinVal==LOW && pinVal==LOW) {
         lowSegmentLength++;
      }
      
      if (lowSegmentLength>0 && prevPinVal==LOW && pinVal==HIGH) {         
         highSegmentLength=1;        
      } 

      if (highSegmentLength>0 && prevPinVal==HIGH && pinVal==HIGH) {
         highSegmentLength++;
      }    
      
      
  }  
  
  long sum=highCount+lowCount;
  long percentageby100=(lowCount*10000)/sum;
  float percentageby100f=percentageby100; 
  float percentage=percentageby100f/100.0;
  return percentage;
}


